using System.Collections.Concurrent;
using System.Globalization;
using System.IO.Compression;


namespace NalogGarLoader.Model.GarRepositoryReader;

public class GarZipFileRepositoryReader : GarRepositoryReader
{
    public GarZipFileRepositoryReader(string sourcePath, HashSet<string> tableImportSet)
        : base(sourcePath, tableImportSet)
    {
    }

    protected override void ReadGarVersion()
    {
        using var zip = ZipFile.OpenRead(this.SourcePath);
        var versionFileEntry = zip.GetEntry("version.txt");

        if (versionFileEntry is null)
            return;

        using var zipEntryStream = versionFileEntry.Open();
        using StreamReader sr = new(zipEntryStream);

        if (DateOnly.TryParse(sr.ReadLine()?.Trim(), CultureInfo.InvariantCulture, DateTimeStyles.None, out DateOnly parsedDateOnly))
            this.GarVersion = parsedDateOnly;
    }

    public override IEnumerator<GarRepositoryEntry> GetEnumerator()
    {
        Queue<string>? zipEntries = new Queue<string>();

        using (var zip = ZipFile.OpenRead(this.SourcePath))
        {            
            foreach (var entry in zip.Entries)
            {
                string? garType = this.ParseGarType(entry.Name);

                if (string.IsNullOrEmpty(garType) || !this.TableImportSet.Contains(garType))
                   continue;

                zipEntries.Enqueue(entry.FullName);
            }
        }

        while (zipEntries.Count > 0)
        {
            string zipEntryName = zipEntries.Dequeue();

            yield return new GarRepositoryEntry(
                zipEntryName,
                this.GarVersion,
                this.ParseGarType(zipEntryName)!,
                this.GetFileStream,
                Path.GetDirectoryName(zipEntryName)!.Split(Path.DirectorySeparatorChar).Single()
                );
        }
    }

    protected override Stream GetFileStream(GarRepositoryEntry garRepositoryEntry)
    {
        var zip = ZipFile.OpenRead(this.SourcePath);

        ZipArchiveEntry zipEntry = zip.GetEntry(garRepositoryEntry.FullFileName) ?? throw new NullReferenceException($"Ошибка получение файла {garRepositoryEntry.FullFileName} из архива {this.SourcePath}");

        return zipEntry.Open(); 
    }
}